// geometry.cpp
//

#include "geometry.h"
#include "bstring.h"

//#include <vector>

namespace simple{
    //
    //Point
    //
    // Since this object won't change, we don't need any versioning

    BString& operator<< (BString& stream, const Point& point)
    {
        BString bstr;
        bstr << point.x() << point.y();

        stream << bstr;
        return stream;
    }


    BString& operator>> (BString& stream, Point& point)
    {
        BString bstr;
        stream >> bstr;

        int x, y;
        bstr >> x >> y;

        point = Point (x, y);
        return stream;
    }

    //
    // Rect
    //
    // Since this object won't change, we don't need any versioning

    Rect::Rect () : _ul (Point(0,0)), _width (0), _height (0) {}

    Rect::Rect (Point ul, unsigned int width, unsigned int height)
    : _ul (ul), _width (width), _height (height) {}

    Rect::Rect (Point ul, Point lr)
    : _ul (ul), _width (lr.x()-ul.x()), _height (lr.y()-ul.y()) {}

    Rect::Rect (int x0, int y0, int unsigned width, unsigned int height)
    : _ul (Point(x0,y0)), _width (width), _height (height)  {}


    Point Rect::lr () const 
    { return Point (_ul.x() + _width, _ul.y() + _height); }

    bool Rect::operator == (const Rect& r) const
    { return (ul() == r.ul() && width() == r.width() && height() == r.height()); }

    bool Rect::within (const Point& p) const
    {
        Point lr (_ul.x() + _width, _ul.y()+_height);
        return (_ul.x() <= p.x()) && (lr.x() > p.x()) &&
               (_ul.y() <= p.y()) && (lr.y() > p.y());
    }


    Rect Rect::intersect (const Rect& r) const
    {
        // Get the corner points.
        const Point& ul1 = ul();
        const Point& ul2 = r.ul();

        int x = Max(ul1.x(), ul2.x());
        int y = Max(ul1.y(), ul2.y());
        int w = Min(ul1.x() + width(), ul2.x() + r.width()) - x;
        int h = Min(ul1.y() + height(), ul2.y() + r.height()) - y;

        if(w < 0 || h < 0)
        {
            // No intersection 没有相交
            return Rect();
        }

        return Rect(x, y, w, h);
    }

    void Rect::expand (int x, int y)
    {
        if (!isNull()) {
            _ul     += Point (-x, -y);
            _width  += 2*x;
            _height += 2*y;
        }
    }

    BString& operator<< (BString& stream, const Rect& point)
    {
        BString bstr;

        bstr << point.x0() << point.y0() << point.width() << point.height();

        stream << bstr;
        return stream;
    }

    BString& operator>> (BString& stream, Rect& rect)
    {
        BString bstr;
        stream >> bstr;

        int x, y;
        unsigned int w, h;
        bstr >> x >> y >> w >> h;

        rect = Rect (x, y, w, h);
        return stream;
    }
}